package org.summer.generator.writer.impl;

import org.summer.generator.StringUtil;
import org.summer.generator.log.Logger;
import org.summer.generator.log.LoggerManager;
import org.summer.generator.vo.MethodInfo;
import org.summer.generator.writer.AbstractJavaFileWriter;

import java.util.*;

/**
 * web请求控制接口文件写入类
 *
 * @author gvp9132
 * @date 2024/10/25 19:49
 * @since 1.0.0
 */
public class ControllerFileWriter extends AbstractJavaFileWriter {
    private static final Logger log = LoggerManager.getLogger(ControllerFileWriter.class);
    @Override
    public void execute() {
        String pn = project.getControllerPackageName();
         // 解析类信息
        List<MethodInfo> mds = parseMethodDefinitions(writer.getControllerParentInterface());
        channel.writer(getPackageDefinition(pn));
        channel.writerEmptyLine();
        channel.writerEmptyLine();
        channel.writerNewline(IMPORT_LOMBOK_RAC);
        channel.writerNewline("import org.springframework.web.bind.annotation.*;");
        String classDefinition = getClaasDefinition(pn,writer.getControllerParentInterface());
        String dependencyClass = getDependencyClass(project.getServicePackageName());
        String serviceObject = StringUtil.firstLetterLowerCase(dependencyClass);
        importSet.forEach(channel::writerNewline);
        channel.writerNewline(table.getEntityImportStr());
        channel.writerEmptyLine();
        channel.writerNewline(CLASS_REMARK.formatted(table.getRemark() + ",web接口控制层实现类"));
        String annotation_0 = "@RequestMapping(\"%s\")";
        channel.writerNewline("@RestController");
        channel.writerNewline(annotation_0.formatted(writer.getRequestPrefix() + "/" + table.getTableName()));
        channel.writerNewline("@RequiredArgsConstructor");
        channel.writerNewline(classDefinition);
        channel.writerNewline(FIELD_PREFIX + dependencyClass + " " + serviceObject + LINE_END);
        channel.writerEmptyLine();
        mds.forEach(methodInfo -> writerMethod(methodInfo, serviceObject,null));
        channel.writer(BLOCK_END);
//        log.debug("需要导入类: ", importSet);
    }

    @Override
    protected void writerMethod(MethodInfo method, String previousObject, String loadMethodName) {
//        log.debug("写入方法: ", method);
        StringBuilder methodDef = new StringBuilder(METHOD_PREFIX);
        methodDef.append(method.getReturnType());
        methodDef.append(SPACING);
        methodDef.append(method.getMethodName());
        String param = getParam(method);
        methodDef.append(param);
        methodDef.append(BLOCK_START).append(LINE);
        String mapping = loadReturnAndParseMappings(method, previousObject, methodDef);
        methodDef.append(TAB).append(BLOCK_END).append(LINE);
        channel.writerNewline(mapping);
        channel.writerNewline(ANNOTATION_OVERRIDE);
        channel.writerNewline(methodDef.toString());
    }

    /**
     * 加载方法返回体内容,并解析Mapping注解
     *
     * @param method        方法信息
     * @param serviceObject 服务对象名称
     * @param methodDef     方法定义
     */
    private String loadReturnAndParseMappings(MethodInfo method, String serviceObject, StringBuilder methodDef) {
        final String methodName = method.getMethodName();
        String returnStr = "";
        String callMethodName = "";
        String urlParam = "";
        for (int i = 0; i < method.getParameter().size(); i++) {
            urlParam += ("/{" + method.getParameter().get(i).split(" ")[1] + "}");
        }
        // 处理查找方法
        if (methodName.startsWith(CONTROLLER_QUERY)) {
            callMethodName = methodName.replace(CONTROLLER_QUERY, SERVICE_FIND);
            if (method.getMethodName().contains("List")) {
                returnStr = "\t@GetMapping(\"/list%s\")".formatted(urlParam);
            }
            if (methodName.contains("Page")) {
                returnStr = "\t@GetMapping(\"/page%s\")".formatted(urlParam);
            }
            if (methodName.contains("Id")) {
                returnStr = "\t@GetMapping(\"/one/{id}\")";
            }
            if (methodName.contains("Limit")) {
                returnStr = "\t@GetMapping(\"/limit%s\")".formatted(urlParam);
            }
        }
        // 处理添加方法
        if (methodName.startsWith(CONTROLLER_SAVE)) {
            returnStr = "\t@PutMapping";
            callMethodName = methodName.replace(CONTROLLER_SAVE, SERVICE_ADD);
        }
        // 处理删除方法
        if (methodName.startsWith(CONTROLLER_DELETE)) {
            returnStr = "\t@DeleteMapping(\"%s\")".formatted(urlParam);
            callMethodName = methodName.replace(CONTROLLER_DELETE, SERVICE_REMOVE);
        }
        // 处理更新方法
        if (methodName.startsWith(CONTROLLER_UPDATE)) {
            returnStr = "\t@PostMapping";
            callMethodName = methodName.replace(CONTROLLER_UPDATE, SERVICE_MODIFY);
        }
        String mr = parseMethodReturn(serviceObject, callMethodName, method.getParameter());
        methodDef.append(mr).append(LINE);
        return returnStr;
    }

    /**
     * 获取方法定义字符串中的方法参数
     */
    private String getParam(MethodInfo method) {
        StringBuilder param = new StringBuilder("(");
        if (!method.getParameter().isEmpty()) {
            for (int i = 0; i < method.getParameter().size(); i++) {
                if (i > 0) {
                    param.append(", ");
                }
                String t = method.getParameter().get(i).split(" ")[0];
                if (t.equals(table.getTableUpperName())) {
                    param.append("@RequestBody ").append(method.getParameter().get(i));
                } else {
                    param.append("@PathVariable ").append(method.getParameter().get(i));
                }
            }
        }
        param.append(")");
        return param.toString();
    }

    /**
     * 获取方法反回体中内容
     */
    private String parseMethodReturn(String serviceObject, String callMethodName, List<String> parameter) {
//        log.debug("解析方法返回体: ", serviceObject, callMethodName, parameter);
        StringBuilder param = new StringBuilder("(");
        for (int i = 0; i < parameter.size(); i++) {
            if (i > 0) {
                param.append(", ");
            }
            param.append(parameter.get(i).split(" ")[1]);
        }
        param.append(")");
        return METHOD_RETURN_PREFIX + serviceObject + "." + callMethodName + param + LINE_END;
    }
}
